package bubbleindex;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 *
 * @author ttrott
 */
public class updateData {

    private static final List<String> Categories = new ArrayList();
    private static List<Integer> updatelist = new ArrayList();
    public static volatile int errors;
    
    public static void updateData() {
        BubbleIndex.setThreads();
        getTypes();
        
        Map<String, Integer> errorsPerCategory = new HashMap<>();
        for (String Category : Categories) {
            errors = 0;
            List<String> Selections = new ArrayList();
            List<String> Sources = new ArrayList();
            List<String> quandlDataSet = new ArrayList();
            List<String> quandlDataName = new ArrayList();
            List<Integer> quandlColumn = new ArrayList();
            List<String> isYahooIndex = new ArrayList();
            getCategoryList(Category, Selections, Sources, quandlDataSet, quandlDataName, 
                    quandlColumn, isYahooIndex);
                    
            ExecutorService executor = Executors.newFixedThreadPool(BubbleIndex.ThreadNumber);
            
            List<Callable<Integer>> callables = 
                    new ArrayList<>();
            
            for (int j = 0; j < Selections.size(); j++) {
                callables.add(new UpdateRunnable(Category, Selections.get(j), Sources.get(j),
                        quandlDataSet.get(j), quandlDataName.get(j), quandlColumn.get(j),
                        isYahooIndex.get(j)));
            }
            
            List<Future<Integer>> results;
            try {
                results = executor.invokeAll(callables);

                for (Future<Integer> futures : results) {
                    try {
                        updatelist.add(futures.get());
                    } catch (ExecutionException ex) {
                        errors++;
                        System.out.println("Execution Exception. Code 016.");
                    }
                }
                
            } catch (InterruptedException ex) {
                System.out.println("Interrupted Exception. Code 017.");
            }
            
            executor.shutdownNow();
            final int finalErrorNumber = errors;
            errorsPerCategory.put(Category, finalErrorNumber);
            updatelist = new ArrayList();
        }
        checkForErrors(errorsPerCategory);       
        BubbleIndex.displayOutput("Update Done!", false); 
    }
    
    /**
     * 
     */
    private static void getTypes() {
        try {
            Charset charset = Charset.forName("UTF-8");
            Path filepath = FileSystems.getDefault().getPath(Indices.getFilePath() + 
                    "ProgramData" + Indices.filePathSymbol + "UpdateCategories.csv");
            BufferedReader reader = Files.newBufferedReader(filepath, charset);
            String line;
            while ((line = reader.readLine()) != null) {
                Categories.add(line);
            }
        
        } catch (IOException x) {
            System.out.println("IO Exception. Code 018.");
            BubbleIndex.displayOutput("Failed to Read File: UpdateCategories.csv", false);      
        }
    }

    /**
     * 
     * @param Category
     * @param Selections
     * @param DataTypes
     * @param quandlDataSet
     * @param quandlDataName
     * @param quandlColumn
     * @param isYahooIndex 
     */
    private static void getCategoryList(String Category, List<String> Selections, 
            List<String> DataTypes, List<String> quandlDataSet, List<String> quandlDataName,
            List<Integer> quandlColumn, List<String> isYahooIndex) {
        try {
            Charset charset = Charset.forName("UTF-8");
            Path filepath = FileSystems.getDefault().getPath(Indices.getFilePath() + 
                    "ProgramData" + Indices.filePathSymbol + Category + Indices.filePathSymbol + 
                    "UpdateSelection.csv");
            BufferedReader reader = Files.newBufferedReader(filepath, charset);
            
            //These files have headers
            String line = reader.readLine();
            while ((line = reader.readLine()) != null) {
                String[] splits = line.split(",");
                Selections.add(splits[0]);
                DataTypes.add(splits[1]);
                quandlDataSet.add(splits[2]);
                quandlDataName.add(splits[3]);
                quandlColumn.add(Integer.parseInt(splits[4]));
                isYahooIndex.add(splits[5]);
            }
        
        } catch (IOException x) {
            System.out.println("IO Exception. Code 019.");
            final String cat = Category;
            BubbleIndex.displayOutput("Failed to Get Selections From: " + 
                            cat + "/UpdateSelection.csv", false);               
        }
    }

    /**
     * 
     */
    private static void checkForErrors(Map<String, Integer> errorsPerCategory) {
        for (Map.Entry<String, Integer> errors : errorsPerCategory.entrySet()) {
            final String categoryName = errors.getKey();
            final int errorNumber = errors.getValue();
            BubbleIndex.displayOutput(categoryName + ": Errors or missing files = " + errorNumber, false);  
        }
    }
}